package com.uex.dev.manage.common.aop;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author wangc
 * @create 2023/9/27
 * @description controller方法监控, 包含入参、出参、执行时长(毫秒)
 */
@Component
@Aspect
@Slf4j
public class MonitorAspect {

    /**
     * 最大长度
     */
    private static final Integer MAX_LENGTH = 300;

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) || @annotation(org.springframework.web.bind.annotation.GetMapping) || @annotation(org.springframework.web.bind.annotation.PostMapping) || @annotation(org.springframework.web.bind.annotation.DeleteMapping) ||@annotation(org.springframework.web.bind.annotation.PutMapping) || @annotation(org.springframework.web.bind.annotation.PatchMapping) || @annotation(org.springframework.web.bind.annotation.RequestMapping))")
    public void pointCut() {
    }


    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        String className = null;
        String methodName = null;

        try {
            Object[] args = joinPoint.getArgs();
            className = joinPoint.getSignature().getDeclaringType().getSimpleName();
            methodName = joinPoint.getSignature().getName();
            log.info("start class:[{}], method:[{}], args:[{}]", className, methodName, Arrays.toString(args));
            Long start = System.currentTimeMillis();
            Object result = joinPoint.proceed();
            Long end = System.currentTimeMillis();
            log.info("end class:[{}], method:[{}], result:[{}], cost:[{}]", className, methodName, shortString(result), end - start);
            return result;
        } catch (Throwable ex) {
            log.error("error class:[{}], method:[{}], error:[{}]", className, methodName, ex);
            throw ex;
        }
    }

    private String shortString(Object o) {
        if (o == null) {
            return "";
        }
        String input = o.toString();
        if (StringUtils.isEmpty(input)) {
            return input;
        }
        int length = input.length();
        if (length > MAX_LENGTH) {
            return "";
        }
        return input;
    }
}
